package com.ella.common.security.service;
import com.ella.common.constants.RedisConstants;
import com.ella.common.security.context.AuthenticationContextHolder;
import com.ella.common.security.exception.UserCountLockException;
import com.ella.common.security.exception.UserLoginLimitException;
import com.ella.entity.SysUser;
import com.ella.entity.security.LoginUser;
import com.ella.service.ISysMenuService;
import com.ella.service.ISysUserService;
import com.ella.utils.RedisCache;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Set;

@Service
public class UserDetailsServiceImpl  implements UserDetailsService {
	@Resource
	private ISysUserService sysUserService;

	@Resource
	private RedisCache redisCache;

    @Resource
	private BCryptPasswordEncoder  bCryptPasswordEncoder;

	@Resource
	private ISysMenuService  ISysMenuService;
	@Override
	public UserDetails loadUserByUsername(String loginName){


		//spring-security查询用户是由存在
		SysUser sysUser = sysUserService.getByUsername(loginName);
		if (sysUser == null) {
			throw new UserLoginLimitException("用户名不存在！");
		} else if ("1".equals(sysUser.getStatus())) {
			throw new UserCountLockException("该用户账号被封禁，具体请联系管理员！");
		}
		//判断登录次数同时校验密码
		identifyLoginCountAndPasswordMatch(sysUser);
		//查询用户的权限0
		Set<String> userPermissions = ISysMenuService.getMenuPermissionByUserId(sysUser.getUserId());

		return new LoginUser(sysUser.getUserId(),sysUser,userPermissions);
	}

	private void identifyLoginCountAndPasswordMatch(SysUser sysUser) {

        try{
			//查询用户登录尝试的次数
			String loginTryKey = RedisConstants.LOGIN_TRY_KEY_PRE + sysUser.getUserId();
			Integer count = redisCache.getCacheObject(loginTryKey);
			if (count == null) {
				redisCache.setCacheObject(loginTryKey, 0);
			}
			if (count > RedisConstants.LOGIN_TRY_MAX_COUNT) {
				sysUser.setStatus("1");
				//封禁账号
				sysUserService.updateById(sysUser);
				//重置缓存
				redisCache.setCacheObject(loginTryKey, 0);
	// TODO 这个异常既是用户名或者密码错误异常也是登录尝试次数已用完异常 所以想要抛出这个异常需要专门使用
				throw new UserLoginLimitException("你的登录尝试次数已用完,请联系管理员解封账号");
			}
			//从AuthenticationContextHolder中获取用户的密码 TODO =>来自于前端传过来的数据
			Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext();
			String password = usernamePasswordAuthenticationToken.getCredentials().toString();
			//校验用户名和密码是否一
			// 致
			if (!bCryptPasswordEncoder.matches(password,sysUser.getPassword())) {
				//验证不通过，将redis中的登录次数加一
				count++;
				redisCache.setCacheObject(loginTryKey, count);
			}
		}finally {
        	AuthenticationContextHolder.clearContext();
		}

	}

}
